#include "core/ObfuscatorEngine.h"
#include "core/ClassObfuscator.h"
#include "core/PropertyObfuscator.h"
#include "core/MethodObfuscator.h"
#include "core/TrashCodeGenerator.h"
#include "core/CodeValidator.h"
#include "core/WhitelistManager.h"
#include "database/DatabaseManager.h"
#include <QDir>
#include <QDirIterator>
#include <QFile>
#include <QTextStream>
#include <QJsonDocument>
#include <QJsonArray>
#include <QDateTime>

ObfuscatorEngine::ObfuscatorEngine(QObject *parent)
    : QObject(parent)
    , m_classObfuscator(std::make_unique<ClassObfuscator>())
    , m_propertyObfuscator(std::make_unique<PropertyObfuscator>())
    , m_methodObfuscator(std::make_unique<MethodObfuscator>())
    , m_trashCodeGen(std::make_unique<TrashCodeGenerator>())
    , m_validator(std::make_unique<CodeValidator>())
    , m_whitelist(std::make_unique<WhitelistManager>())
{
    // 加载默认白名单
    m_whitelist->loadDefaultWhitelist();
}

ObfuscatorEngine::~ObfuscatorEngine() = default;

void ObfuscatorEngine::setProjectPath(const QString &path)
{
    m_projectPath = path;
}

void ObfuscatorEngine::setConfig(const ObfuscationConfig &config)
{
    m_config = config;
}

ObfuscationResult ObfuscatorEngine::obfuscate()
{
    ObfuscationResult result;
    
    emit obfuscationStarted();
    emit progressUpdated(0, "开始混淆处理...");
    
    // 1. 备份项目
    emit progressUpdated(10, "备份项目文件...");
    if (!backupProject()) {
        result.errorMessage = "备份项目失败";
        emit errorOccurred(result.errorMessage);
        return result;
    }
    
    // 2. 扫描项目文件
    emit progressUpdated(20, "扫描项目文件...");
    QStringList files = scanProjectFiles();
    if (files.isEmpty()) {
        result.errorMessage = "未找到可处理的文件";
        emit errorOccurred(result.errorMessage);
        return result;
    }
    
    // 3. 收集所有需要混淆的符号
    emit progressUpdated(30, "分析代码结构...");
    QMap<QString, QString> allMappings;
    
    // 4. 类名混淆
    if (m_config.obfuscateClasses) {
        emit progressUpdated(40, "混淆类名...");
        auto classMappings = m_classObfuscator->generateMappings(files, m_whitelist.get());
        allMappings.insert(classMappings);
        result.classesRenamed = classMappings.size();
    }
    
    // 5. 属性混淆
    if (m_config.obfuscateProperties) {
        emit progressUpdated(50, "混淆属性名...");
        auto propMappings = m_propertyObfuscator->generateMappings(files, m_whitelist.get());
        allMappings.insert(propMappings);
        result.propertiesRenamed = propMappings.size();
    }
    
    // 6. 方法混淆
    if (m_config.obfuscateMethods) {
        emit progressUpdated(60, "混淆方法名...");
        auto methodMappings = m_methodObfuscator->generateMappings(files, m_whitelist.get());
        allMappings.insert(methodMappings);
        result.methodsRenamed = methodMappings.size();
    }
    
    // 7. 应用混淆映射
    emit progressUpdated(70, "应用混淆映射...");
    if (!applyMappings(allMappings)) {
        result.errorMessage = "应用混淆映射失败";
        emit errorOccurred(result.errorMessage);
        return result;
    }
    
    // 8. 注入垃圾代码
    if (m_config.injectTrashCode) {
        emit progressUpdated(80, "注入垃圾代码...");
        result.trashCodeInjected = m_trashCodeGen->injectCode(files);
    }
    
    // 9. 验证结果
    emit progressUpdated(90, "验证混淆结果...");
    if (!validate()) {
        result.errorMessage = "代码验证失败";
        emit errorOccurred(result.errorMessage);
        return result;
    }
    
    // 10. 保存映射记录
    emit progressUpdated(95, "保存混淆记录...");
    result.mappings = allMappings;
    result.success = true;
    
    // 缓存最后的映射，用于导出与历史查看
    m_lastMappings = allMappings;
    emit progressUpdated(100, "混淆完成!");
    emit obfuscationCompleted(result);
    
    return result;
}

bool ObfuscatorEngine::validate()
{
    return m_validator->validateProject(m_projectPath);
}

bool ObfuscatorEngine::rollback(const QString &versionId)
{
    // 实现回滚逻辑
    QString backupPath = QString("%1/.obfuscator/backups/%2").arg(m_projectPath).arg(versionId);
    if (!QDir(backupPath).exists()) {
        emit errorOccurred("备份版本不存在");
        return false;
    }
    
    // 恢复备份
    QDir backupDir(backupPath);
    QDir projectDir(m_projectPath);
    
    // 这里应该实现完整的文件恢复逻辑
    return true;
}

QJsonObject ObfuscatorEngine::getHistory()
{
    QJsonObject history;
    // 从数据库读取历史记录
    QJsonArray arr = DatabaseManager::instance().getObfuscationHistory(100);
    history["records"] = arr;
    return history;
}

bool ObfuscatorEngine::exportMappings(const QString &filePath)
{
    // 导出最近应用的映射
    if (m_lastMappings.isEmpty()) return false;
    QJsonObject root;
    QJsonArray arr;
    for (auto it = m_lastMappings.cbegin(); it != m_lastMappings.cend(); ++it) {
        QJsonObject item;
        item["original"] = it.key();
        item["obfuscated"] = it.value();
        arr.append(item);
    }
    root["mappings"] = arr;
    QJsonDocument doc(root);
    QFile f(filePath);
    if (!f.open(QIODevice::WriteOnly)) return false;
    f.write(doc.toJson(QJsonDocument::Compact));
    f.close();
    return true;
}

QStringList ObfuscatorEngine::scanProjectFiles()
{
    QStringList files;
    QDirIterator it(m_projectPath, 
                   QStringList() << "*.m" << "*.mm" << "*.h" << "*.swift",
                   QDir::Files, 
                   QDirIterator::Subdirectories);
    
    while (it.hasNext()) {
        QString filePath = it.next();
        
        // 排除路径检查
        bool excluded = false;
        for (const QString &excludePath : m_config.excludePaths) {
            if (filePath.contains(excludePath)) {
                excluded = true;
                break;
            }
        }
        
        if (!excluded) {
            files.append(filePath);
        }
    }
    
    return files;
}

bool ObfuscatorEngine::backupProject()
{
    QString timestamp = QDateTime::currentDateTime().toString("yyyyMMdd_HHmmss");
    QString backupPath = QString("%1/.obfuscator/backups/%2").arg(m_projectPath).arg(timestamp);
    
    QDir().mkpath(backupPath);
    
    // 这里应该实现完整的备份逻辑
    // 简化版本：只创建备份目录
    return QDir(backupPath).exists();
}

bool ObfuscatorEngine::applyMappings(const QMap<QString, QString> &mappings)
{
    // 应用混淆映射到所有文件
    QStringList files = scanProjectFiles();
    
    for (const QString &filePath : files) {
        QFile file(filePath);
        if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) {
            continue;
        }
        
        QString content = file.readAll();
        file.close();
        
        // 应用所有映射
        QMapIterator<QString, QString> it(mappings);
        while (it.hasNext()) {
            it.next();
            content.replace(it.key(), it.value());
        }
        
        // 写回文件
        if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
            return false;
        }
        
        QTextStream out(&file);
        out << content;
        file.close();
    }
    
    return true;
}